package com.huterox.todoscheduler.core.execute;

import com.huterox.todoscheduler.annotate.*;
import com.huterox.todoscheduler.core.enumType.TodoItemElementType;
import com.huterox.todoscheduler.core.execute.proxy.TodoItemExBean;
import com.huterox.todoscheduler.core.execute.proxy.TodoListExBean;
import com.huterox.todoscheduler.core.wapper.TodoItemMethodWrapper;
import com.huterox.todoscheduler.handler.TodoItemAfterRunningHandler;
import com.huterox.todoscheduler.handler.TodoItemBeforeCreateHandler;
import com.huterox.todoscheduler.handler.TodoItemBeforeRunningHandler;
import com.huterox.todoscheduler.handler.TodoItemErrorHandler;

import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * 负责将方法解析出来
 * */
public class TodoItemFactory implements Serializable {

    //当这个方法返回null的时候，说明创建失败
    public static TodoItemExBean getInstance(TodoItemMethodWrapper todoItemMethodWrapper, TodoListExBean todoListExBean){

        TodoItemExBean todoItemExBean = new TodoItemExBean();
        todoItemExBean.setOrder(todoItemMethodWrapper.getOrder());
        todoItemExBean.setTodoItemElementType(todoItemMethodWrapper.getTodoItemElementType());
        todoItemExBean.setIdx(todoItemMethodWrapper.getIdx());
        todoItemExBean.setWrapperMethod(todoItemMethodWrapper.getWrapperMethod());
        todoItemExBean.setWrapperClass(todoItemMethodWrapper.getWrapperClass());
        todoItemExBean.setWrapperInstance(todoItemMethodWrapper.getWrapperInstance());

        //解析注解
        Method wrapperMethod = todoItemMethodWrapper.getWrapperMethod();
        wrapperMethod.setAccessible(true);
        if(wrapperMethod.isAnnotationPresent(TodoItemBeforeCreate.class)){
            //这个时候要先去执行一下这个初始化创建的代码
            TodoItemBeforeCreate annotationTodoItemBeforeCreate = wrapperMethod.getAnnotation(TodoItemBeforeCreate.class);
            Class<TodoItemBeforeCreateHandler>[] todoItemBeforeCreates = annotationTodoItemBeforeCreate.todoItemBeforeCreates();
            Class<TodoItemBeforeCreateHandler> todoItemBeforeCreateHandlerClass = todoItemBeforeCreates[todoItemExBean.getIdx()];
            try {
                TodoItemBeforeCreateHandler todoItemBeforeCreateHandler = todoItemBeforeCreateHandlerClass.newInstance();
                //把这个状态Wrapper给它，这个时候是直接执行这个家伙
                try {
                    todoItemBeforeCreateHandler.concierge(todoItemExBean.getStateWrapper(),todoListExBean.getStateWrapper());
                }catch (Exception e){
                    //判断一下类型，是属于哪一种，是那种可以跳过执行的清单项
                    if(todoItemExBean.getTodoItemElementType()== TodoItemElementType.CONTINUTEITEM){
                        //继续happy执行往下走继续
                        System.err.println("当前清单项创建失败执行方法："+wrapperMethod.getName()
                                        +"对应的类为："+todoItemExBean.getWrapperClass().getName()
                                );
                        e.printStackTrace();
                    }else {
                        //不能继续往下happy了，直接先执行修复
                        try {
                            todoItemBeforeCreateHandler.repair(todoItemExBean.getStateWrapper(),todoListExBean.getStateWrapper());
                        }catch (Exception e1){
                            //连修复都G了，没了
                            e1.printStackTrace();
                        }
                        return null;
                    }
                    //还是必须要强制执行的清单项
                    e.printStackTrace();
                }

            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        if(wrapperMethod.isAnnotationPresent(TodoItemBefore.class)){
            TodoItemBefore annotationTodoItemBefore = wrapperMethod.getAnnotation(TodoItemBefore.class);
            Class<TodoItemBeforeRunningHandler>[] todoItemBeforeRunningHandlerClasses = annotationTodoItemBefore.todoItemBefores();
            Class<TodoItemBeforeRunningHandler> todoItemBeforeRunningHandlerClass = todoItemBeforeRunningHandlerClasses[todoItemExBean.getIdx()];
            TodoItemBeforeRunningHandler todoItemBeforeRunningHandler = null;
            try {
                todoItemBeforeRunningHandler = todoItemBeforeRunningHandlerClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemBeforeRunningHandler(todoItemBeforeRunningHandler);
        }

        if(wrapperMethod.isAnnotationPresent(TodoItemAfterHandler.class)){
            TodoItemAfterHandler annotationTodoItemAfterHandler = wrapperMethod.
                    getAnnotation(TodoItemAfterHandler.class);

            Class<TodoItemAfterRunningHandler>[] todoItemAfterRunningHandleClasses = annotationTodoItemAfterHandler.
                    todoItemAfterHandlers();

            Class<TodoItemAfterRunningHandler> todoItemAfterRunningHandleClass = todoItemAfterRunningHandleClasses[todoItemExBean.getIdx()];

            TodoItemAfterRunningHandler todoItemAfterRunningHandler = null;
            try {
                todoItemAfterRunningHandler = todoItemAfterRunningHandleClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemAfterRunningHandler(todoItemAfterRunningHandler);
        }

        if(wrapperMethod.isAnnotationPresent(TodoItemError.class)) {
            TodoItemError annotationTodoItemError = wrapperMethod.getAnnotation(TodoItemError.class);
            Class<TodoItemErrorHandler>[] todoItemErrorHandlerClasses = annotationTodoItemError.todoItemErrors();
            Class<TodoItemErrorHandler> todoItemErrorHandlerClass = todoItemErrorHandlerClasses[todoItemExBean.getIdx()];
            TodoItemErrorHandler todoItemErrorHandler = null;
            try {
                todoItemErrorHandler = todoItemErrorHandlerClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
                return null;
            }
            todoItemExBean.setTodoItemErrorHandler(todoItemErrorHandler);
        }

        //此时我们的清单项封装实例化完毕
        return todoItemExBean;
    }
}
